/*
 * FileName：StringUtil.java
 * <p>
 * Copyright (c) 2017-2020, <a href="http://www.webcsn.com">hermit (794890569@qq.com)</a>.
 * <p>
 * Licensed under the GNU General Public License, Version 3 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/gpl-3.0.html
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package com.g4m.baselib.tool;

import org.apache.commons.lang3.StringUtils;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * 功能：字符串工具类
 * <p>
 * hermit
 * <p>
 * mobile enterprise application platform
 * Version 0.1
 */
public class G4mStringUtil extends StringUtils {

    public static String _HREF_URL_REGEX = "(http:|https:)//[^[A-Za-z0-9\\._\\?%&+\\-=/#!]]*";
    public static final String EMPTY_STRING = "";
    private static char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
    private static final char IntChars[] = "1234567890".toCharArray();

    /**
     * 获得int
     *
     * @param val 值
     * @return int 值
     */
    public static int getInt(String val) {
        return getInt(val, -1);
    }

    /**
     * 获得int
     *
     * @param val 值
     * @return int 值
     */
    public static int getInt(Object val) {
        if (val == null) return -1;
        return getInt(val.toString(), -1);
    }

    /**
     * 获得int
     *
     * @param val 值
     * @param def 默认
     * @return 实际
     */
    public static int getInt(Object val, int def) {
        try {
            return Integer.parseInt(val.toString().trim());
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 获得long
     *
     * @param val 值
     * @return 实际
     */
    public static long getLong(String val) {
        return getLong(val, -1);
    }

    /**
     * 获得long
     *
     * @param object 值
     * @return 实际值
     */
    public static long getLong(Object object) {
        return getLong(get(object.toString(), "-1"), -1);
    }

    /**
     * 获得long
     *
     * @param val 值
     * @param def 默认
     * @return 实际
     */
    public static long getLong(String val, long def) {
        try {
            return Long.parseLong(val.trim());
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * 获得boolean
     *
     * @param val 值
     * @return 实际
     */
    public static boolean getBoolean(String val) {
        return getBoolean(val, false);
    }

    /**
     * 获得boolean
     *
     * @param val 值
     * @param def 默认
     * @return 实际
     */
    public static boolean getBoolean(String val, boolean def) {
        if (StringUtils.isBlank(val)) return def;
        try {
            return Boolean.parseBoolean(val);
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 获得double
     *
     * @param value 值
     * @return 实际
     */
    public static double getDouble(String value) {
        return getDouble(value, 0.00);
    }

    /**
     * 获得double
     *
     * @param value 值
     * @param def   默认
     * @return 实际
     */
    public static double getDouble(String value, double def) {
        try {
            return Double.valueOf(value).doubleValue();
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 返回Trim后的值
     *
     * @param val 值
     * @return 实际
     */
    public static String getTrim(String val) {
        val = getNonNull(val);
        return val.trim();
    }

    /**
     * 如果为null返回空字符串
     *
     * @param val 值
     * @return 实际
     */
    public static String getNonNull(String val) {
        return get(val, EMPTY_STRING);
    }

    /**
     * 获得BigDecimal
     *
     * @param str 值
     * @return 实际
     */
    public static BigDecimal getBigDecimal(String str) {
        try {
            BigDecimal bd = new BigDecimal(str);
            return bd;
        } catch (Exception e) {
            return BigDecimal.valueOf(-1.00);
        }
    }

    /**
     * 获得BigDecimal
     *
     * @param str 字符串
     * @param def 默认
     * @return 实际
     */
    public static BigDecimal getBigDecimal(String str, double def) {
        try {
            return new BigDecimal(str);
        } catch (Exception e) {
            return BigDecimal.valueOf(def);
        }
    }

    /**
     * yes/no转换成true/false
     *
     * @param aValue 值
     * @return 实际
     */
    public static final String getBooleanFromYesNo(String aValue) {
        if (aValue.equalsIgnoreCase("yes")) {
            return "true";
        }
        return "false";
    }

    /**
     * 替换字符串
     *
     * @param text        原始文本
     * @param replaced    要替换内容
     * @param replacement 替换内容
     * @return 字符串
     */
    public static String replace(String text, String replaced, String replacement) {
        StringBuffer ret = new StringBuffer();
        String temp = text;

        while (temp.indexOf(replaced) > -1) {
            ret.append(temp.substring(0, temp.indexOf(replaced)) + replacement);

            temp = temp.substring(temp.indexOf(replaced) + replaced.length());
        }

        ret.append(temp);

        return ret.toString();
    }

    /**
     * 字符串替换 正反向
     *
     * @param sIni                字符串
     * @param sFrom               位置
     * @param sTo                 结束位置
     * @param caseSensitiveSearch 替换
     * @return 字符串
     */
    public static String replaceString(String sIni, String sFrom, String sTo, boolean caseSensitiveSearch) {
        int i = 0;
        String s = new String(sIni);
        StringBuffer result = new StringBuffer();
        if (caseSensitiveSearch) {
            i = s.indexOf(sFrom);
        } else {
            i = s.toLowerCase().indexOf(sFrom.toLowerCase());
        }

        while (i != -1) {
            result.append(s.substring(0, i));
            result.append(sTo);

            s = s.substring(i + sFrom.length());

            if (caseSensitiveSearch) {
                i = s.indexOf(sFrom);
            } else {
                i = s.toLowerCase().indexOf(sFrom.toLowerCase());
            }
        }

        result.append(s);

        return result.toString();
    }

    /**
     * 将字符串转换成Vector通过Token
     *
     * @param sIn        字符
     * @param sTokenizer 解密
     * @return 数组
     */
    public static List<String> tokenize(String sIn, String sTokenizer) {
        if (StringUtils.isBlank(sIn)) return new Vector<String>();
        Vector<String> vToken = new Vector<String>();
        int nOffset = 0;
        int nOffset1 = 0;

        nOffset1 = sIn.indexOf(sTokenizer, nOffset);

        while (nOffset1 > -1) {
            if (nOffset1 > nOffset) {
                vToken.add(sIn.substring(nOffset, nOffset1));
            } else {
                vToken.add(EMPTY_STRING);
            }

            nOffset = nOffset1 + sTokenizer.length();
            nOffset1 = sIn.indexOf(sTokenizer, nOffset);
        }

        if (nOffset < sIn.length()) {
            vToken.add(sIn.substring(nOffset, sIn.length()));
        } else {
            vToken.add(EMPTY_STRING);
        }

        return vToken;
    }

    /**
     * 将字符串转换成字符数组通过token
     *
     * @param sIn        字符串
     * @param sTokenizer 序列号
     * @return 字符串
     */
    public static String[] tokenizeToArray(String sIn, String sTokenizer) {
        if (StringUtils.isBlank(sIn)) {
            return new String[0];
        }
        List<String> vToken = tokenize(sIn, sTokenizer);
        String[] tokenArray = new String[vToken.size()];
        for (int i = 0; i < vToken.size(); i++) {
            tokenArray[i] = getTrim((String) vToken.get(i));
        }
        return tokenArray;
    }

    /**
     * 删除不能成为文件名的字符
     *
     * @param fileStr 字符串
     * @return 值
     */
    public static String removeIllegalFileChars(String fileStr) {
        String replacedFileStr = fileStr;

        replacedFileStr = replace(replacedFileStr, " ", "_");
        replacedFileStr = replace(replacedFileStr, "&", EMPTY_STRING);
        replacedFileStr = replace(replacedFileStr, "%", EMPTY_STRING);
        replacedFileStr = replace(replacedFileStr, ",", EMPTY_STRING);
        replacedFileStr = replace(replacedFileStr, ";", EMPTY_STRING);
        replacedFileStr = replace(replacedFileStr, "/", "_");

        return replacedFileStr;
    }

    /**
     * 获得字符串中的指点子字符串
     *
     * @param strIn  字符串
     * @param start  开始位置
     * @param length 长度
     * @return 字符串
     */
    public static String substring(String strIn, int start, int length) {
        String strOut = null;

        if (strIn != null) {
            strOut = EMPTY_STRING;

            if (start < strIn.length() && length > 0) {
                if (start + length < strIn.length()) {
                    strOut = strIn.substring(start, start + length);
                } else {
                    strOut = strIn.substring(start, strIn.length());
                }
            }
        }

        return strOut;
    }

    /**
     * 随机生成length位数字字符串
     *
     * @param length 长度
     * @return 字符串
     */
    public static final String getRandomLengthDigit(int length) {
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < length; i++) {
            str.append(IntChars[(int) (Math.random() * 10)]);
        }
        return str.toString();
    }

    /**
     * 随即生成length位字符串
     *
     * @param length 长度
     * @return 字符串
     */
    public static final String getRandomLengthString(int length) {
        if (length < 1)
            return null;
        char ac[] = new char[length];
        for (int j = 0; j < ac.length; j++)
            ac[j] = chars[new Random().nextInt(71)];

        return new String(ac);
    }

    /**
     * 随即生成i位中文
     *
     * @param length 长度
     * @return 字符串
     */
    public static final String getRandomLengthChineseString(int length) {
        StringBuilder sb = new StringBuilder();
        for (int i = length; i > 0; i--) {
            sb.append(getRandomChinese());
        }
        return sb.toString();
    }

    /**
     * 随机产生中文,长度范围为start-end
     *
     * @param start 开始
     * @param end   结束
     * @return 字符串
     */
    public static String getRandomLengthChiness(int start, int end) {
        StringBuilder sb = new StringBuilder();
        int length = new Random().nextInt(end + 1);
        if (length < start) {
            return getRandomLengthChiness(start, end);
        } else {
            for (int i = 0; i < length; i++) {
                sb.append(getRandomChinese());
            }
        }
        return sb.toString();
    }

    /**
     * 随机获得中文
     *
     * @return 字符串
     */
    public static String getRandomChinese() {
        String str = null;
        int highPos, lowPos;
        Random random = new Random();
        highPos = (176 + Math.abs(random.nextInt(39)));
        lowPos = 161 + Math.abs(random.nextInt(93));
        byte[] b = new byte[2];
        b[0] = (new Integer(highPos)).byteValue();
        b[1] = (new Integer(lowPos)).byteValue();
        try {
            str = new String(b, "GB2312");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return str;
    }

//    /**
//     * 获得XML中的CDATA格式数据
//     *
//     * @param text
//     * @return
//     */
//    public static String getCDATAData(String text) {
//        if (!ValidateUtil.isNotNull(text)) return EMPTY_STRING;
//        return new StringBuffer().append("<![CDATA[").append(text).append("]]>").toString();
//    }

    /**
     * 编码
     *
     * @param str     要编码的字符串
     * @param charset 编码类型
     * @param ss      可选,原来的类型
     * @return 字符串
     */
    public static String encode(String str, String charset, String... ss) {
        if (StringUtils.isBlank(str)) return EMPTY_STRING;
        if (StringUtils.isBlank(charset)) return str;
        try {
            if (ss != null && ss.length > 0) return new String(str.getBytes(ss[0]), charset);
            else return new String(str.getBytes(), charset);
        } catch (UnsupportedEncodingException e) {
            return str;
        }
    }

    /**
     * 如果为null返回默认值
     *
     * @param obj 对象
     * @param def 默认
     * @return 字符串
     */
    public static String get(Object obj, String def) {
        if (obj == null) return def;
        return StringUtils.isBlank(obj.toString()) ? def : obj.toString();
    }

    /**
     * 删除额外的空格,保证一个空格
     *
     * @param str 字符串
     * @return 字符串
     */
    public static String removeExtraBlanks(String str) {
        if (StringUtils.isBlank(str)) return EMPTY_STRING;
        char[] chars = str.toCharArray();
        int finalIndex = 0;
        int spaceCount = 0;
        for (int i = 0; i < chars.length; ++i) {
            if (chars[i] != ' ') {
                chars[finalIndex] = chars[i];
                ++finalIndex;
                spaceCount = 0;
            } else if (chars[i] == ' ' && finalIndex == 0) {
            } else if (chars[i] == ' ' && spaceCount == 0) {
                chars[finalIndex] = chars[i];
                ++finalIndex;
                ++spaceCount;
            } else if (chars[i] == ' ' && spaceCount > 0) {
                ++spaceCount;
            }
        }
        for (int i = finalIndex; i < chars.length; ++i) {
            chars[i] = ' ';
        }
        return String.valueOf(chars);
    }

    /**
     * 删除所有空格
     *
     * @param str 字符串
     * @return 字符串
     */
    public static String removeBlanks(String str) {
        if (str == null || str.equals(EMPTY_STRING))
            return str;
        char ac[] = str.toCharArray();
        char ac1[] = new char[ac.length];
        int i = 0;
        for (int j = 0; j < ac.length; j++)
            if (!Character.isSpaceChar(ac[j]))
                ac1[i++] = ac[j];

        return new String(ac1, 0, i);
    }

    /**
     * 二行制转字符串
     *
     * @param b 二进制
     * @return 字符串
     */
    public static String byte2hex(byte[] b) {
        StringBuilder hs = new StringBuilder();
        String stmp = EMPTY_STRING;
        for (int n = 0; n < b.length; n++) {
            stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
            if (stmp.length() == 1)
                hs.append("0").append(stmp);
            else
                hs.append(stmp);
        }
        return hs.toString().toUpperCase();
    }

    /**
     * 获得List的字符串连接
     *
     * @param list  列表
     * @param split 分隔符
     * @return 字符串
     */
    public static String getStringFromList(List<String> list, String... split) {
        if (list == null) {
            return EMPTY_STRING;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0, j = list.size(); i < j; i++) {
            sb.append(list.get(i));
            if (split != null && split.length > 0) sb.append(split[0]);
        }
        return sb.toString();
    }

    /**
     * 连接对象
     *
     * @param objs 对象
     * @return 字符串
     */
    public static String concat(Object... objs) {

        if (objs == null || objs.length < 1) return EMPTY_STRING;
        StringBuilder sb = new StringBuilder();
        for (Object obj : objs) {
            sb.append(obj == null ? EMPTY_STRING : obj.toString());
        }
        return sb.toString();
    }

//    /**
//     * 连接数组
//     *
//     * @param array
//     * @param split
//     * @return
//     */
//    public static String getStringFromArray(String[] array, String... split) {
//
//        if (array == null) return EMPTY_STRING;
//        StringBuilder sb = new StringBuilder();
//        for (int i = 0; i < array.length; i++) {
//            if (i > 0 && split != null && ValidateUtil.isNotNull(split[0])) sb.append(split[0]);
//            sb.append(array[i]);
//        }
//        return sb.toString();
//    }

    /**
     * 连接list
     *
     * @param connector 连接器
     * @param list      数组
     * @return 字符串
     */
    public static String concatList(String connector, List<?> list) {
        return concatArray(connector, list.toArray(new Object[list.size()]));
    }

    /**
     * 连接数组
     *
     * @param connector 连接器
     * @param objects   对象
     * @param <T>       泛型
     * @return 字符串
     */
    public static <T> String concatArray(String connector, T... objects) {

        if (objects == null || objects.length < 1) return EMPTY_STRING;
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < objects.length; i++) {
            if (objects[i] == null || StringUtils.isBlank(objects[i].toString())) continue;
            if (i > 0) sb.append(connector);
            sb.append(objects[i].toString());
        }
        return sb.toString();
    }

    /**
     * 自由组合列表
     *
     * @param list 列表
     * @return 字符串
     */
    public static List<String> combined(List<List<String>> list) {
        if (list.size() == 1) {
            return list.get(0);
        } else if (list.size() == 2) {
            return combined(list.get(0), list.get(1));
        } else {
            List<String> tempList = new ArrayList<String>();
            for (int i = list.size(); i > 0; i--) {
                tempList = combined(list.get(i - 1), tempList);
            }
            return tempList;
        }
    }

    /**
     * 自由组合两列表
     *
     * @param list1 列表
     * @param list2 列表
     * @return 字符串
     */
    public static List<String> combined(List<String> list1, List<String> list2) {
        if (list2.isEmpty()) return list1;
        List<String> results = new ArrayList<String>();
        for (String str1 : list1) {
            for (String str2 : list2) {
                results.add(str1 + "," + str2);
            }
        }
        return results;
    }

//    /**
//     * 字符串替换
//     *
//     * @param text  原字符串
//     * @param terms Map类型 Key:要替换内容 value:替换后内容
//     * @return
//     */
//    public static String replaceAll(String text, Map<String, String> terms) {
//        String textResult = text;
//        for (String key : terms.keySet()) {
//            if (ValidateUtil.isNotNull(key) && ValidateUtil.isNotNull(terms.get(key)))
//                textResult = Pattern.compile(key).matcher(textResult).replaceAll(terms.get(key));
//        }
//        return textResult;
//    }

    /**
     * 正则表达式替换
     *
     * @param str         源字符串
     * @param pattern     要替换的模式
     * @param replacement 替换成的内容
     * @return 字符串
     */
    public static String regexReplace(String str, String pattern, String replacement) {
        if (StringUtils.isBlank(str)) return EMPTY_STRING;
        if (StringUtils.isBlank(pattern)) return str;
        return str.replaceAll(pattern, replacement);
    }

    /**
     * 正则替换
     *
     * @param str       源字符串
     * @param pattern   要替换的模式
     * @param replace   替换成的内容
     * @param connector 连接器
     * @param def       默认值
     * @return 字符串
     */
    public static String regex(String str, String pattern, String replace, String connector, String def) {
        if (str == null || pattern == null || connector == null) return null;
        Pattern p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
        Matcher matcher = p.matcher(str);
        StringBuffer sb = new StringBuffer();
        int i = 0;
        for (i = 0; matcher.find(); i++) {
            if (i > 0) sb.append(connector);
            matcher.appendReplacement(sb, replace);
        }
        if (i > 0) matcher.appendTail(sb).append(def);
        else sb.append(str);
        return sb.toString();
    }

    /**
     * 查找符合正则的表达式的字符串
     *
     * @param str     字符串
     * @param pattern 正则
     * @param index   位置
     * @return 字符串
     */
    public static String regexFind(String str, String pattern, int index) {
        if (StringUtils.isBlank(str)) return EMPTY_STRING;
        Pattern p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
        Matcher matcher = p.matcher(str);
        for (int i = 1; matcher.find(); i++) {
            if (i == index) {
                return matcher.group();
            }
        }
        return EMPTY_STRING;
    }

//    /**
//     * 将html文本去除成普通文本
//     *
//     * @param html
//     * @param style simple\basic\basicWithImages\relaxed\none
//     * @return
//     */
//    public static String getText(String html, String style) {
//        if (StringUtils.isBlank(html)) return html;
//        if (ValidateUtil.isEqualsIgnoreCase("simple", style)) {
//            return Jsoup.clean(html, Whitelist.simpleText());
//        } else if (ValidateUtil.isEqualsIgnoreCase("basic", style)) {
//            return Jsoup.clean(html, Whitelist.basic());
//        } else if (ValidateUtil.isEqualsIgnoreCase("basicWithImages", style)) {
//            return Jsoup.clean(html, Whitelist.basicWithImages());
//        } else if (ValidateUtil.isEqualsIgnoreCase("relaxed", style)) {
//            return Jsoup.clean(html, Whitelist.relaxed());
//        } else {
//            return Jsoup.clean(html, Whitelist.none());
//        }
//    }

    /**
     * 将普通文本中的链接提取成超链接
     *
     * @param text 文本
     * @return 字符串
     */
    public static String getHrefText(String text) {
        try {
            Pattern pattern = Pattern.compile(_HREF_URL_REGEX);
            Matcher matcher = pattern.matcher(text);
            StringBuffer result = new StringBuffer();
            String url;
            while (matcher.find()) {
                url = matcher.group();
                StringBuffer replace = new StringBuffer();
                replace.append("<a href=\"").append(url);
                replace.append("\" target=\"_blank\">" + url + "</a>");
                matcher.appendReplacement(result, replace.toString());
            }
            matcher.appendTail(result);
            return get(result.toString(), text);
        } catch (Exception e) {
            return text;
        }
    }

//    /**
//     * 字符串解析Map
//     *
//     * @param text
//     * @param termSplit
//     * @param keySplit
//     * @return
//     */
//    public static Map<String, String> getMap(String text,
//                                             String termSplit, String keySplit) {
//
//        Map<String, String> values = null;
//        if (ValidateUtil.isNotNull(text)) {
//            values = new LinkedHashMap<String, String>();
//            for (String line : StringUtil.tokenize(text, termSplit)) {
//                if (StringUtils.isBlank(line)) continue;
//                String[] t = line.split(keySplit);
//                if (t.length == 1) {
//                    values.put(StringUtil.getTrim(t[0]), StringUtil.getTrim(t[0]));
//                    continue;
//                }
//                if (t.length != 2) continue;
//                values.put(t[0], StringUtil.getTrim(t[1]));
//            }
//        }
//        return values == null ? new HashMap<String, String>() : values;
//    }

    /**
     * 通过字节截断字符串长度
     *
     * @param str    字符串
     * @param length 长度
     * @param more   更多
     * @return 字符串
     */
    public static String substringByByte(String str, int length, String more) {
        int reInt = 0;
        String reStr = EMPTY_STRING;
        if (StringUtils.isBlank(str)) return EMPTY_STRING;
        char[] tempChar = str.toCharArray();
        for (int kk = 0; (kk < tempChar.length && length > reInt); kk++) {
            String s1 = String.valueOf(tempChar[kk]);
            byte[] b = s1.getBytes();
            reInt += b.length;
            reStr += tempChar[kk];
        }
        if (length == reInt || (length == reInt - 1))
            reStr += more;
        return reStr;
    }

    /**
     * 获得指定小数位
     *
     * @param value 值
     * @param fixed 小数长度
     * @return 数字
     */
    public static BigDecimal getFixedBigDecimal(String value, int fixed) {
        try {
            BigDecimal result = new BigDecimal(value);
            return result.setScale(fixed, BigDecimal.ROUND_HALF_UP);
        } catch (Exception e) {

        }
        return BigDecimal.ZERO;
    }
//
//    /**
//     * 获得正则匹配的字符串
//     *
//     * @param text
//     * @param pattern
//     * @param group
//     * @return
//     */
//    public static String getMatcherGroup(String text, String pattern, int group) {
//        if (ValidateUtil.isNotNull(text) && ValidateUtil.isNotNull(pattern)) {
//            Pattern p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
//            Matcher matcher = p.matcher(text);
//            if (matcher.matches()) {
//                return matcher.group(group);
//            }
//        }
//        return null;
//    }

//    /**
//     * 判断字符串编码
//     *
//     * @param str
//     * @return
//     */
//    public static String getCharacterEncoding(String str) {
//        return CharsetUtil.getStringEncode(str);
//    }
//
//    /**
//     * 判断字节数组编码
//     *
//     * @param array
//     * @return
//     */
//    public static String getCharacterEncoding(byte[] array) {
//        return CharsetUtil.getEncode(array);
//    }

    /**
     * 首字母大写
     *
     * @param str 字符串
     * @return 大写
     */
    public static String toUpperCaseFirstChar(String str) {
        int strLen;
        if (str == null || (strLen = str.length()) == 0) {
            return str;
        }
        return new StringBuilder(strLen)
                .append(Character.toTitleCase(str.charAt(0)))
                .append(str.substring(1))
                .toString();
    }

    /**
     * 首字母小写
     *
     * @param str 字符串
     * @return 字符串
     */
    public static String toLowerCaseFirstChar(String str) {
        int strLen;
        if (str == null || (strLen = str.length()) == 0) {
            return str;
        }
        return new StringBuilder(strLen)
                .append(Character.toLowerCase(str.charAt(0)))
                .append(str.substring(1))
                .toString();
    }

}
